package com.youth.framework.util;

import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;

public class DefaultCryptor
implements Cryptor
{
private static final char[] HEX_CHARS = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };

private static final byte[] KEY_BYTES = { 65, 112, 97, 99, 104, 101, 67, 111, 109, 109, 111, 110, 115, 86, 70, 83 };
private static final int INDEX_NOT_FOUND = -1;
private static final int BITS_IN_HALF_BYTE = 4;
private static final char MASK = '\017';

public String encrypt(String plainKey)
  throws Exception
{
  byte[] input = plainKey.getBytes();
  SecretKeySpec key = new SecretKeySpec(KEY_BYTES, "AES");

  Cipher cipher = Cipher.getInstance("AES");

  cipher.init(1, key);

  byte[] cipherText = new byte[cipher.getOutputSize(input.length)];
  int ctLength = cipher.update(input, 0, input.length, cipherText, 0);
  ctLength += cipher.doFinal(cipherText, ctLength);
  return encode(cipherText);
}

public String decrypt(String encryptedKey)
  throws Exception
{
  SecretKeySpec key = new SecretKeySpec(KEY_BYTES, "AES");
  Cipher cipher = Cipher.getInstance("AES");
  cipher.init(2, key);
  byte[] decoded = decode(encryptedKey);
  byte[] plainText = new byte[cipher.getOutputSize(decoded.length)];
  int ptLength = cipher.update(decoded, 0, decoded.length, plainText, 0);
  ptLength += cipher.doFinal(plainText, ptLength);
  return new String(plainText).substring(0, ptLength);
}

private String encode(byte[] bytes)
{
  StringBuilder builder = new StringBuilder();

  for (int i = 0; i < bytes.length; i++)
  {
    builder.append(HEX_CHARS[(bytes[i] >> 4 & 0xF)]);
    builder.append(HEX_CHARS[(bytes[i] & 0xF)]);
  }
  return builder.toString();
}

private byte[] decode(String str)
{
  int length = str.length() / 2;
  byte[] decoded = new byte[length];
  char[] chars = str.toCharArray();
  int index = 0;
  for (int i = 0; i < chars.length; i++)
  {
    int id1 = indexOf(HEX_CHARS, chars[i]);
    if (id1 == -1)
    {
      throw new IllegalArgumentException("Character " + chars[i] + " at position " + i + " is not a valid hexidecimal character");
    }

    int id2 = indexOf(HEX_CHARS, chars[(++i)]);
    if (id2 == -1)
    {
      throw new IllegalArgumentException("Character " + chars[i] + " at position " + i + " is not a valid hexidecimal character");
    }

    decoded[(index++)] = ((byte)(id1 << 4 | id2));
  }
  return decoded;
}

private int indexOf(char[] array, char valueToFind)
{
  if (array == null)
  {
    return -1;
  }
  for (int i = 0; i < array.length; i++)
  {
    if (valueToFind == array[i])
    {
      return i;
    }
  }
  return -1;
}
}